using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Sixeyed.CodeGeneration.Metadata.Enums;
using Sixeyed.CodeGeneration.Metadata.Interfaces;

namespace Sixeyed.CodeGeneration.UI
{
    /// <summary>
    /// Control for selecting a metadata item from a list or from user input
    /// </summary>
    public partial class ItemSelection : UserControl
    {
        public delegate void ItemSelectionChangedHandler(object sender);
        public event ItemSelectionChangedHandler ItemSelectionChanged;

        private IMetadataProvider _provider;
        private string _lastUriLoaded;

        /// <summary>
        /// Default constructor
        /// </summary>
        public ItemSelection()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Gets/sets the metadata provider used for the selection
        /// </summary>
        public IMetadataProvider Provider
        {
            get { return this._provider; }
            set
            {
                this._provider = value;
                if (this._provider != null && (string.IsNullOrEmpty(this._lastUriLoaded) || this._provider.Source.Uri != this._lastUriLoaded))
                {
                    this.LoadSelection();
                    this._lastUriLoaded = this._provider.Source.Uri;
                }
            }
        }

        /// <summary>
        /// Returns the selected items
        /// </summary>
        /// <remarks>
        /// For collections, returns an IMetadataItem for each item checked in the list;
        /// for user input, returns a single IMetadataItem with the user-provided string as its key
        /// </remarks>
        /// <returns></returns>
        public List<IMetadataItem> GetSelectedItems()
        {
            List<IMetadataItem> items = new List<IMetadataItem>();
            switch (this._provider.SelectionType)
            {
                case ProviderSelectionType.Collection:
                    foreach (ListViewItem item in this.lvwCollection.CheckedItems)
                    {
                        items.Add(this._provider.GetItem(item.Text));
                    }
                    break;

                case ProviderSelectionType.Input:
                    items.Add(this._provider.GetItem(this.txtInput.Text));
                    break;
            }
            return items;
        }

        #region Private instance methods

        /// <summary>
        /// Loads UI with item choice in listview, or textbox for user input
        /// </summary>
        private void LoadSelection()
        {
            this.lvwCollection.Visible = this.txtInput.Visible = false;
            if (this._provider != null)
            {
                switch (this._provider.SelectionType)
                {
                    case ProviderSelectionType.Collection:
                        //load available collection for user to select:
                        this.lvwCollection.Visible = true;
                        this.txtInput.Visible = false;
                        this.lvwCollection.Items.Clear();
                        try
                        {
                            List<string> itemNames = this._provider.GetItemNames();
                            foreach (string itemName in itemNames)
                            {
                                this.lvwCollection.Items.Add(new ListViewItem(itemName));
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(string.Format("Unable to connect to metadata source: {0}", ex.Message), "Metadata Source Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                        break;

                    case ProviderSelectionType.Input:
                        //show textbox to capture user input:
                        this.txtInput.Visible = true;
                        this.lvwCollection.Visible = false;
                        this.txtInput.Clear();
                        break;
                }
            }
        }

        private void lvwCollection_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            NotifySelectionChanged();
        }

        private void txtInput_Leave(object sender, EventArgs e)
        {
            this.NotifySelectionChanged();
        }

        private void NotifySelectionChanged()
        {
            if (this.ItemSelectionChanged != null)
            {
                this.ItemSelectionChanged(this);
            }
        }

        #endregion
    }
}
